﻿// <copyright file="LoggingAspect.cs" company="Beuth Hochschule für Technik">
// Breakdown - Configure your Windows 7 Firewall
// Copyright (C) 2009 Stefan "dersteps@gmail.com" Matyba
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; 
// either version 3 of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses/.
// </copyright>
// <author>Stefan Matyba</author>
// <email>dersteps@gmail.com</email>
// <date>2009-11-10</date>
// <summary>Aspect that enables AOP logging</summary>

namespace Breakdown.Aspects
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NLog;
    using PostSharp.Laos;

    /// <summary>
    /// Logging aspect - enables Breakdown to do AOP logging
    /// </summary>
    [Serializable]
    public class Logged : OnMethodBoundaryAspect
    {
        /// <summary>
        /// NLog logger instance
        /// </summary>
        private static Logger _logger = LogManager.GetLogger("DEBUGLOG");

        /// <summary>
        /// Overridden.
        /// Is invoked every time a marked method is entered (before execution)
        /// </summary>
        /// <param name="eventArgs">Event arguments for invoked method</param>
        public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
            _logger.Info(this.BuildLogEntry("[ENTRY] ", eventArgs.Method.Name, eventArgs.Method.DeclaringType.FullName));

            base.OnEntry(eventArgs);
        }

        /// <summary>
        /// Overridden.
        /// Is invoked every time a marked method throws an exception(during execution)
        /// </summary>
        /// <param name="eventArgs">Event arguments for invoked method</param>
        public override void OnException(MethodExecutionEventArgs eventArgs)
        {
            _logger.Error(this.BuildLogEntry("[EXCEPTION] ", eventArgs.Method.Name, eventArgs.Method.DeclaringType.FullName));
            base.OnException(eventArgs);
        }

        /// <summary>
        /// Overridden.
        /// Is invoked every time a marked method is exited (after execution)
        /// </summary>
        /// <param name="eventArgs">Event arguments for invoked method</param>
        public override void OnExit(MethodExecutionEventArgs eventArgs)
        {
            _logger.Info(this.BuildLogEntry("[EXIT] ", eventArgs.Method.Name, eventArgs.Method.DeclaringType.FullName));
            base.OnExit(eventArgs);
        }

        /// <summary>
        /// Overridden.
        /// Is invoked every time a marked method succeeds (after execution)
        /// </summary>
        /// <param name="eventArgs">Event arguments for invoked method</param>
        public override void OnSuccess(MethodExecutionEventArgs eventArgs)
        {
            _logger.Info(this.BuildLogEntry("[SUCCESS] ", eventArgs.Method.Name, eventArgs.Method.DeclaringType.FullName));
            base.OnSuccess(eventArgs);
        }

        /// <summary>
        /// Builds a log entry to be written to a logger instance
        /// </summary>
        /// <param name="status">The status of method invocation (ENTRY, SUCCESS, EXIT or EXCEPTION)</param>
        /// <param name="methodName">Name of invoked method</param>
        /// <param name="declaringType">Name of declaring type</param>
        /// <returns>Log entry, containing status, method name and declaring type</returns>
        private string BuildLogEntry(string status, string methodName, string declaringType)
        {
            StringBuilder sb = new StringBuilder(" [DEBUG] ");
            sb.Append(status);
            sb.Append("\t");
            sb.Append(declaringType);
            sb.Append("::");
            sb.Append(methodName);

            return sb.ToString();
        }
    }
}
